﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Threading;

namespace Tibco.ServiceModel
{
    internal abstract class TibcoChannelBase : IChannel, ICommunicationObject
    {
        private readonly Action<TimeSpan> _closeMethod;

        private readonly BindingContext _context;

        private readonly Action<TimeSpan> _openMethod;

        private CommunicationState _state;

        protected BindingContext Context
        {
            get
            {
                return this._context;
            }
        }

        public CommunicationState State
        {
            get
            {
                return this._state;
            }
        }

        private TibcoChannelBase()
        {
            this._state = CommunicationState.Created;
            TibcoChannelBase tibcoChannelBase = this;
            this._closeMethod = new Action<TimeSpan>(tibcoChannelBase.Close);
            TibcoChannelBase tibcoChannelBase1 = this;
            this._openMethod = new Action<TimeSpan>(tibcoChannelBase1.Open);
        }

        protected TibcoChannelBase(BindingContext context) : this()
        {
            this._context = context;
        }

        public virtual void Abort()
        {
            this.Close();
        }

        public virtual IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this._closeMethod.BeginInvoke(timeout, callback, state);
        }

        public virtual IAsyncResult BeginClose(AsyncCallback callback, object state)
        {
            return this._closeMethod.BeginInvoke(this._context.Binding.CloseTimeout, callback, state);
        }

        public virtual IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this._openMethod.BeginInvoke(timeout, callback, state);
        }

        public virtual IAsyncResult BeginOpen(AsyncCallback callback, object state)
        {
            return this._openMethod.BeginInvoke(this._context.Binding.OpenTimeout, callback, state);
        }

        public abstract void Close(TimeSpan timeout);

        public virtual void Close()
        {
            this.Close(this._context.Binding.CloseTimeout);
        }

        public virtual void EndClose(IAsyncResult result)
        {
            this._closeMethod.EndInvoke(result);
        }

        public virtual void EndOpen(IAsyncResult result)
        {
            this._openMethod.EndInvoke(result);
        }

        public virtual T GetProperty<T>()
        where T : class
        {
            return default(T);
        }

        protected void OnClosed()
        {
            this._state = CommunicationState.Closed;
            if (this.Closed != null)
            {
                this.Closed(this, null);
            }
        }

        protected void OnClosing()
        {
            this._state = CommunicationState.Closing;
            if (this.Closing != null)
            {
                this.Closing(this, null);
            }
        }

        protected void OnFaulted()
        {
            this._state = CommunicationState.Faulted;
            if (this.Faulted != null)
            {
                this.Faulted(this, null);
            }
        }

        protected void OnOpened()
        {
            this._state = CommunicationState.Opened;
            if (this.Opened != null)
            {
                this.Opened(this, null);
            }
        }

        protected void OnOpening()
        {
            this._state = CommunicationState.Opening;
            if (this.Opening != null)
            {
                this.Opening(this, null);
            }
        }

        public abstract void Open(TimeSpan timeout);

        public virtual void Open()
        {
            this.Open(this._context.Binding.OpenTimeout);
        }

        public event EventHandler Closed;

        public event EventHandler Closing;

        public event EventHandler Faulted;

        public event EventHandler Opened;

        public event EventHandler Opening;
    }
}